package cn.iocoder.yudao.module.hs.util;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.util.spring.SpringUtils;
import cn.iocoder.yudao.module.hs.controller.admin.material.vo.MaterialRespVO;
import cn.iocoder.yudao.module.hs.controller.admin.picktaskmaterial.vo.StartPickVO;
import cn.iocoder.yudao.module.hs.controller.admin.scan.vo.ScanInfoRespVO;
import cn.iocoder.yudao.module.hs.dal.dataobject.material.MaterialDO;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.List;
import java.util.concurrent.TimeUnit;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.hs.enums.ErrorCodeConstants.START_PICK_LOCK;

public class RedisUtil {

    private static RedisTemplate redisTemplate;

    static {
        RedisUtil.redisTemplate = SpringUtils.getBean("redisTemplate");
    }

    public static final String PICK_TASK_LOCK_KEY = "START_PICK_LOCK";

    public static final String START_PICK_KEY = "START_PICK";

    public static final String START_PICK_SELECTED_MATERIALS_KEY = "START_PICK_SELECTED_MATERIALS";

    public static final String START_PICK_PICKED_LIST_KEY = "START_PICK_PICKED_LIST";

    public static final String PICKING_MATERIALS_KEY = "PICKING_MATERIALS";

    /**
     * 拣货任务开启时，存储已经开始锁定的物料清单，防止被其他任务拣取
     * @param list
     */
    public static void addPickingMaterials(List<MaterialRespVO> list) {
        List<MaterialRespVO> pickingMaterials = getPickingMaterialsKey();
        if (CollUtil.isNotEmpty(pickingMaterials)) {
            for (MaterialRespVO materialRespVO : list) {
                if (!pickingMaterials.contains(materialRespVO)) {
                    pickingMaterials.add(materialRespVO);
                }
            }
        } else {
            pickingMaterials = list;
        }
        redisTemplate.opsForValue().set(PICKING_MATERIALS_KEY, pickingMaterials);
    }

    public static List<MaterialRespVO> getPickingMaterialsKey() {
        return (List<MaterialRespVO>) redisTemplate.opsForValue().get(PICKING_MATERIALS_KEY);
    }

    public static void removePickingMaterials(String pickTaskCode) {
        List<MaterialRespVO> pickingMaterials = getPickingMaterialsKey();
        pickingMaterials.removeIf(materialRespVO -> pickTaskCode.equals(materialRespVO.getPickTaskCode()));
        redisTemplate.opsForValue().set(PICKING_MATERIALS_KEY, pickingMaterials);
    }

    public static void removePickingMaterialsByModeCode(String modeCode) {
        List<MaterialRespVO> pickingMaterials = getPickingMaterialsKey();
        pickingMaterials.removeIf(materialRespVO -> modeCode.equals(materialRespVO.getModeCode()));
        redisTemplate.opsForValue().set(PICKING_MATERIALS_KEY, pickingMaterials);
    }

    public static void getPickTaskLock(String pickTaskCode, Long userId) {
        String startPickLockKey = PICK_TASK_LOCK_KEY + ":" + pickTaskCode;
        Object lockKey = redisTemplate.opsForValue().get(startPickLockKey);
        if (lockKey == null) {
            setPickTaskLock(pickTaskCode, userId);
        } else {
            if (userId != Long.parseLong(lockKey.toString())) {
                throw exception(START_PICK_LOCK);
            }
        }
    }

    public static void releasePickTaskLock(String pickTaskCode) {
        String startPickLockKey = PICK_TASK_LOCK_KEY + ":" + pickTaskCode;
        redisTemplate.delete(startPickLockKey);
    }

    public static void setPickTaskLock(String pickTaskCode, Long userId) {
        String startPickLockKey = PICK_TASK_LOCK_KEY + ":" + pickTaskCode;
        redisTemplate.opsForValue().set(startPickLockKey, userId, 5 , TimeUnit.MINUTES);
    }

    /**
     * 待拣范围存储到redis中
     *
     * @param pickTaskCode
     */
    public static void startPick(String pickTaskCode, StartPickVO startPickVO) {
        String startPickKey = START_PICK_KEY + ":" + pickTaskCode;
        redisTemplate.opsForValue().set(startPickKey, startPickVO);
    }

    /**
     * 从redis中获取待拣范围
     *
     * @param pickTaskCode
     */
    public static StartPickVO getStartPick(String pickTaskCode) {
        String startPickKey = START_PICK_KEY + ":" + pickTaskCode;
        return (StartPickVO) redisTemplate.opsForValue().get(startPickKey);
    }

    /**
     * 清空待拣范围
     * @param pickTaskCode
     */
    public static void removeStartPick(String pickTaskCode) {
        String startPickKey = START_PICK_KEY + ":" + pickTaskCode;
        redisTemplate.delete(startPickKey);
    }

    public static List<MaterialDO> getSelectedMaterials(String pickTaskCode) {
        String selectedMaterialsKey = START_PICK_SELECTED_MATERIALS_KEY + ":" + pickTaskCode;
        return (List<MaterialDO>) redisTemplate.opsForValue().get(selectedMaterialsKey);
    }

    public static void setSelectedMaterials(String pickTaskCode, List<MaterialDO> list) {
        String selectedMaterialsKey = START_PICK_SELECTED_MATERIALS_KEY + ":" + pickTaskCode;
        redisTemplate.opsForValue().set(selectedMaterialsKey, list);
    }

    public static void removeSelectedMaterials(String pickTaskCode) {
        String selectedMaterialsKey = START_PICK_SELECTED_MATERIALS_KEY + ":" + pickTaskCode;
        redisTemplate.delete(selectedMaterialsKey);
    }

    /**
     * 获取已经扫过的托盘、物料箱、物料记录
     * @param pickTaskCode
     * @return
     */
    public static List<ScanInfoRespVO> getPickedList(String pickTaskCode) {
        String selectedListKey = START_PICK_PICKED_LIST_KEY + ":" + pickTaskCode;
        return (List<ScanInfoRespVO>) redisTemplate.opsForValue().get(selectedListKey);
    }

    /**
     * 将已经扫过的托盘、物料箱、物料记录存入redis
     * @param pickTaskCode
     * @return
     */
    public static void setPickedList(String pickTaskCode, List<ScanInfoRespVO> scanInfoRespVOList) {
        String selectedListKey = START_PICK_PICKED_LIST_KEY + ":" + pickTaskCode;
        redisTemplate.opsForValue().set(selectedListKey, scanInfoRespVOList);
    }
    /**
     * 清空已经扫过的托盘、物料箱、物料记录
     * @param pickTaskCode
     */
    public static void removePickedList(String pickTaskCode) {
        String selectedListKey = START_PICK_PICKED_LIST_KEY + ":" + pickTaskCode;
        redisTemplate.delete(selectedListKey);
    }

    public static void removeAll(String pickTaskCode) {
        releasePickTaskLock(pickTaskCode);
        removePickingMaterials(pickTaskCode);
        removeStartPick(pickTaskCode);
        removeSelectedMaterials(pickTaskCode);
        removePickedList(pickTaskCode);
    }
}
